home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Source Code
/
Visual Basic Source Code.iso
/
vbsource
/
manyth31
/
gif.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-28
|
24KB
|
1,032 lines
/* $change:Code cleanup, minor fixes.$ */
/*
** $id: ssvcid gif.c 1.0 08/03/92 10:01 am$
** Read a Compuserve GIF file into a DIB.
**
** (C) 1992-1993 Larry Widing
*/
#define NOCOMM
#define NOKANJI
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "bitmaps.h"
#define SEG_CBUF 01
#define FASTCALLS 01
#define GET_BYTES 01
#define PAL_SHIFT 0
/*
** Local functions
*/
static short NEAR decoder(short linewidth);
static short init_exp(short size);
static short NEAR get_next_code(void);
static void inittable(void);
static void close_file(void);
/*
** Local variables
*/
static int rowcount; /* row counter for screen */
static int hin = NULL;
static unsigned int height;
static unsigned char dacbox[256][3]; /* Video-DAC (filled in by SETVIDEO) */
static unsigned char decoderline[2049]; /* write-line routines use this */
static unsigned char win_andmask[8];
static unsigned char win_notmask[8];
static unsigned char win_bitshift[8];
static int xdots, ydots, colors;
static int win_xdots, win_ydots;
static unsigned char huge *pixels; /* the device-independent bitmap pixels */
static int pixels_per_byte; /* pixels/byte in the pixmap */
static long pixels_per_bytem1; /* pixels / byte - 1 (for ANDing) */
static int pixelshift_per_byte; /* 0, 1, 2, or 3 */
static int bytes_per_pixelline; /* pixels/line / pixels/byte */
static long win_bitmapsize; /* bitmap size, in bytes */
static int bad_code_count = 0; /* needed by decoder module */
#if SEG_CBUF
static BYTE _seg *cbuf = NULL;
static unsigned int gbuf = 0;
#else
static BYTE FAR *cbuf = NULL;
static BYTE FAR *gbuf = NULL;
#endif
static HANDLE hcbuf = NULL;
static unsigned int gbn = 0;
#define cbufsize (32u * 1024u) // (16u * 1024u)
static int NEAR
get_byte(void)
{
if (gbn == 0)
{
gbn = _lread(hin,cbuf,cbufsize);
#if SEG_CBUF
gbuf = 0;
#else
gbuf = NULL;
#endif
}
if (gbn)
{
--gbn;
#if SEG_CBUF
return (cbuf[gbuf++]) & 0x00ff;
#else
return (*gbuf++) & 0x00ff;
#endif
}
else
return (-1);
}
#if GET_BYTES
static int NEAR
get_bytes(unsigned int count, char *dest)
{
int count2 = count;
if (count <= 0)
{
return count;
}
while (count)
{
if (gbn == 0)
{
gbn = _lread(hin,cbuf,cbufsize);
#if SEG_CBUF
gbuf = NULL;
#else
gbuf = cbuf;
#endif
if (!gbn)
return -1;
}
if (gbn >= count)
{
if (dest != NULL)
{
#if SEG_CBUF
memcpy(dest, cbuf + gbuf, count);
#else
memcpy(dest, gbuf, count);
#endif
}
gbuf += count;
gbn -= count;
count = 0;
}
else
{
if (dest != NULL)
{
#if SEG_CBUF
memcpy(dest, cbuf + gbuf, gbn);
#else
memcpy(dest, gbuf, gbn);
#endif
}
count -= gbn;
dest += gbn;
gbn = 0;
}
}
return count2;
}
#endif
static void NEAR
putcolor(int x, int y, int color)
{
long i;
i = win_ydots - 1 - y;
i = (i * win_xdots) + x;
if (x >= 0 && x < xdots && y >= 0 && y < ydots)
{
if (pixelshift_per_byte == 0)
{
pixels[i] = color % colors;
}
else
{
unsigned int j;
j = i & (unsigned int)pixels_per_bytem1;
i = i >> pixelshift_per_byte;
pixels[i] = (pixels[i] & win_notmask[j]) +
(((unsigned char) (color % colors)) << win_bitshift[j]);
}
}
}
static int NEAR
put_line(int rownum, int leftpt, int rightpt, unsigned char *localvalues)
{
int i, len;
long startloc;
len = rightpt - leftpt;
if (rightpt >= xdots)
{
len = xdots - leftpt;
}
startloc = win_ydots - 1 - rownum;
startloc = (startloc * win_xdots) + leftpt;
if (rownum < 0 || rownum >= ydots || leftpt < 0)
{
return (0);
}
if (pixelshift_per_byte == 0)
{
/*
** Done this way because _fmemcpy() does not handle HUGE pointers
** that can wrap over a selector/segment boundry.
*/
unsigned char huge *ptr = pixels + startloc;
if (HIWORD(ptr) != HIWORD(ptr + len))
{
char *src = (char *)localvalues;
while (len--)
*ptr++ = *src++;
}
else
{
_fmemcpy(ptr, localvalues, len);
}
}
else
{
unsigned int j;
long k;
for (i = 0 ; i <= len ; i++)
{
k = startloc + i;
j = k & (unsigned int)pixels_per_bytem1;
k = k >> pixelshift_per_byte;
pixels[k] = (pixels[k] & win_notmask[j]) +
(((unsigned char) (localvalues[i] % colors)) << win_bitshift[j]);
}
}
putcolor(leftpt, rownum, localvalues[0]);
return (1);
}
static int NEAR
out_line(unsigned char *localvalues, int numberofdots)
{
return (put_line(rowcount++, 0, numberofdots, localvalues));
}
/*
** Main entry decoder
*/
HDIB
ReadGifFile(const char FAR *filename)
{
HDIB dib = (HANDLE)NULL, hbiCurrent;
unsigned numcolors;
unsigned char buffer[16];
unsigned width, finished;
LPBITMAPINFOHEADER lpbi;
RGBQUAD FAR *pRgb;
int status = 0;
int i, j, planes;
DWORD dwBits, dwLen;
OFSTRUCT of;
/* initialize the row count for write-lines */
rowcount = 0;
/* zero out the full write-line */
for (width = 0 ; width < 2049 ; width++)
decoderline[width] = 0;
/* Open the file -- changed to OpenFile by mh */
hin = OpenFile ((LPSTR)filename, (LPOFSTRUCT)&of, OF_READ);
if (hin == -1)
{
return FALSE;
}
hcbuf = GlobalAlloc(GHND,cbufsize);
cbuf = (BYTE FAR *)GlobalLock(hcbuf);
if (cbuf == NULL)
{
close_file();
return FALSE;
}
gbn = 0;
#if SEG_CBUF
gbuf = 0;
#else
gbuf = NULL;
#endif
/* Get the screen description */
for (i = 0 ; i < 13 ; i++)
{
buffer[i] = (unsigned char) status = get_byte();
if (status < 0)
{
close_file();
return FALSE;
}
}
if (strncmp((char *)buffer, "GIF87a", 3) || /* use updated GIF specs */
buffer[3] < '0' || buffer[3] > '9' ||
buffer[4] < '0' || buffer[4] > '9' ||
buffer[5] < 'A' || buffer[5] > 'z')
{
close_file();
return FALSE;
}
planes = (buffer[10] & 0xF) + 1;
if ((buffer[10] & 0x80) == 0) /* color map (better be!) */
{
close_file();
return FALSE;
}
numcolors = 1 << planes;
#if GET_BYTES
if (numcolors * 3 == get_bytes(numcolors * 3, dacbox))
{
#if PAL_SHIFT
for (i = 0 ; i < numcolors ; ++i)
{
for (j = 0 ; j < 3 ; ++j)
{
dacbox[i][j] >>= 2;
}
}
#endif
}
else
{
close_file();
return FALSE;
}
#else
for (i = 0 ; i < numcolors ; i++)
{
for (j = 0 ; j < 3 ; j++)
{
status = get_byte();
if (status < 0)
{
close_file();
return FALSE;
}
dacbox[i][j] = (status & 0x00ff) >> 2;
}
}
#endif
/* Now display one or more GIF objects */
finished = 0;
while (!finished)
{
switch (get_byte())
{
case ';': /* End of the GIF dataset */
finished = 1;
status = 0;
break;
case '!': /* GIF Extension Block */
get_byte(); /* read (and ignore) the ID */
while ((i = get_byte()) > 0) /* get the data length */
#if GET_BYTES
get_bytes(i, NULL);
#else
for (j = 0; j < i; j++)
get_byte(); /* flush the data */
#endif
break;
case ',':
/*
* Start of an image object. Read the image description.
*/
#if GET_BYTES
if (9 != get_bytes(9, buffer))
{
status = -1;
}
else
{
status = 0;
}
#else
for (i = 0; i < 9; i++)
{
buffer[i] = (unsigned char) status = get_byte();
if (status < 0)
{
status = -1;
break;
}
}
#endif
if (status < 0)
{
finished = 1;
break;
}
width = buffer[4] | (buffer[5] << 8);
height = buffer[6] | (buffer[7] << 8);
// fill in DIB stuff
xdots = width;
ydots = height;
colors = numcolors;
if (colors > 16)
colors = 256;
if (colors > 2 && colors < 16)
colors = 16;
win_xdots = (xdots + 3) & 0xFFFC;
win_ydots = ydots;
pixelshift_per_byte = 0;